import 'dart:async';

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: const Text('event loop'),
      ),
      body: _Body(),
    ),
  ));
}

class _Body extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _BodyState();
  }
}

class _BodyState extends State<_Body> {
  @override
  void initState() {
    super.initState();

    _testEventLoop();
//    _officialTest();
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }

  /**
   *  _testEventLoop->sync->1
      async start
      _testEventLoop->scheduleMicrotask->0
      async delayed future...
      async end
      _testEventLoop->sync->2
      _testEventLoop->scheduleMicrotask->from future...
      _testEventLoop->scheduleMicrotask->1
      _testEventLoop->scheduleMicrotask->2
      async delayed future in future...
      _testEventLoop->future
   */
  /// 对于async方法，不管其调用处前面有没有await，都会进入方法并执行同步方法，对于异步的方法，如果有await
  /// event A ->done---->MicroTask queue executes 并不是event queue执行完毕再执行 MicroTask queue
  void _testEventLoop() async {
    print('_testEventLoop->sync->1');
    scheduleMicrotask(() {
      print('_testEventLoop->scheduleMicrotask->0');
    });
    await _asyncMethod();
    print('_testEventLoop->sync->2');
    scheduleMicrotask(() {
      print('_testEventLoop->scheduleMicrotask->1');
    });
    Future.delayed(Duration.zero, () {
      print('_testEventLoop->future');
    }).then((_){});
    scheduleMicrotask(() {
      print('_testEventLoop->scheduleMicrotask->2');
    });
  }

  _asyncMethod() async {
    print('async start');
    await Future.delayed(const Duration(seconds: 0), () {
      print('async delayed future...');
      Future.delayed(Duration.zero, () {
        print('async delayed future in future...');
      });
      scheduleMicrotask(() {
        print('_testEventLoop->scheduleMicrotask->from future...');
      });
    });
    print('async end');

    Future.value(true).then((value){

    });
  }


  _officialTest() {
    print('main #1 of 2');
    scheduleMicrotask(() => print('microtask #1 of 3'));

    new Future.delayed(
        new Duration(seconds: 1), () => print('future #1 (delayed)'));

    new Future(() => print('future #2 of 4'))
        .then((_) => print('future #2a'))
        .then((_) {
      print('future #2b');
      scheduleMicrotask(() => print('microtask #0 (from future #2b)'));
    }).then((_) => print('future #2c'));

    scheduleMicrotask(() => print('microtask #2 of 3'));

    new Future(() => print('future #3 of 4'))
        .then((_) => new Future(() => print('future #3a (a new future)')))
//        .then((_) {new Future(() => print('future #3a (a new future)'));})
        .then((_) => print('future #3b'));

    new Future(() => print('future #4 of 4'));
    scheduleMicrotask(() => print('microtask #3 of 3'));
    print('main #2 of 2');
  }

/*
.then((_) {new Future(() => print('future #3a (a new future)'));})
  main #1 of 2
  main #2 of 2
  microtask #1 of 3
  microtask #2 of 3
  microtask #3 of 3
  future #2 of 4
  future #2a
  future #2b
  future #2c
  microtask #0 (from future #2b)
  future #3 of 4
  future #3b
  future #4 of 4
  future #3a (a new future)
  future #1 (delayed)
   */

/*
.then((_) => new Future(() => print('future #3a (a new future)')))
main #1 of 2
main #2 of 2
microtask #1 of 3
microtask #2 of 3
microtask #3 of 3
future #2 of 4
future #2a
future #2b
future #2c
microtask #0 (from future #2b)
future #3 of 4
future #4 of 4
future #3a (a new future)
future #3b
future #1 (delayed)
 */
}
